﻿
Imports std
Imports xmlctrl
Imports elpmis
Imports lpmsengi

Public Class login
    Inherits requestProcessor

    Public Const _pathidentity As String = loginPathIdentity

    Shared Sub New()
        assert(strstartwith(defaultlogin._pathidentity, network.pathSeperator))
    End Sub

    Public Overrides Function pathidentity() As String
        Return _pathidentity
    End Function

    Private Shared Function forceUpdate(ByVal context As httpContext) As Boolean
        Return context.url().queryExist(query.forceUpdate)
    End Function

    Private Shared Function _processLogin(ByVal context As httpContext, _
                                          ByVal id As String, _
                                          ByVal pwderr As Boolean) As Boolean
        elpmis.context.insertThreadStaticVariable("id", typeDefination.string, id)
        elpmis.context.insertThreadStaticVariable("pwderr", typeDefination.bool, pwderr)
        elpmis.context.insertThreadStaticVariable("forceUpdate", typeDefination.bool, forceUpdate(context))
        elpmis.context.insertThreadStaticVariable("returnUrl",
                                                  typeDefination.string,
                                                  context.url().query(query.returnUrl))
        Return context.createControl(New nameLpmsControl("login")).render()
    End Function

    Protected Overridable Function processLogin(ByVal context As httpContext, _
                                                Optional ByVal id As String = Nothing) As Boolean
        Return _processLogin(context, id, False)
    End Function

    Protected Overridable Function processRegister(ByVal context As httpContext, _
                                                   ByVal id As String) As Boolean
        elpmis.context.insertThreadStaticVariable("id", typeDefination.string, id)
        Return context.createControl(New nameLpmsControl("jump_register")).render()
    End Function

    Protected Overridable Function processPasswordError(ByVal context As httpContext, _
                                                        ByVal id As String) As Boolean
        Return _processLogin(context, id, True)
    End Function

    Protected Overridable Function processSuccess(ByVal context As httpContext, _
                                                  ByVal id As String, _
                                                  ByVal host As String, _
                                                  ByVal returnUrl As String, _
                                                  ByVal userRandomKey As String, _
                                                  ByVal userSiteRandomKey As String) As Boolean
        elpmis.context.insertThreadStaticVariable("id", typeDefination.string, id)
        elpmis.context.insertThreadStaticVariable("host", typeDefination.string, host)
        elpmis.context.insertThreadStaticVariable("returnUrl", typeDefination.string, returnUrl)
        elpmis.context.insertThreadStaticVariable("userSiteRandomKey", typeDefination.string, userSiteRandomKey)
        Return context.createControl(New nameLpmsControl("login_success")).render()
    End Function

    Private Function processSuccess(ByVal context As httpContext, _
                                    ByVal id As String, _
                                    ByVal updateRandomKey As Boolean, _
                                    ByVal forceUpdate As Boolean) As Boolean
        Dim urk As String = Nothing
        If updateRandomKey Then
            If Not setUserRandomKey(context, id, forceUpdate, urk) Then
                raiseError(errorHandle.errorType.warning, "cannot setUserRandomKey, id ", id)
            End If
        Else
            If Not userRandomKey(id, urk) Then
                raiseError(errorHandle.errorType.warning, "cannot get userRandomKey, id ", id)
            End If
        End If

        Dim returnUrl As String = Nothing
        returnUrl = context.url().query(query.returnUrl)
        Dim host As String = Nothing
        If isemptystring(returnUrl) Then
            returnUrl = getContextServer(context) + defaultlogin._pathidentity
        End If
        Dim userSiteRandomKey As String = Nothing
        If Not setUserSiteRandomKey(id, returnUrl, urk, host, userSiteRandomKey) Then
            raiseError(errorHandle.errorType.warning, _
                       "cannot set user / site random key to cache, id ", id, ", returnUrl ", returnUrl)
        End If

        Return processSuccess(context, id, host, returnUrl, urk, userSiteRandomKey)
    End Function

    Public NotOverridable Overrides Function process(ByVal context As httpContext) As Boolean
        assert(Not context Is Nothing)
        Dim id As String = Nothing
        If context.userInput(query.id, cookie.id, id) Then
            Dim pwd As String = Nothing
            pwd = context.url().query(query.password)
            If Not isemptystring(pwd) Then
                Dim realpwd As String = Nothing
                If userPassword(id, realpwd) Then
                    If strsame(pwd, realpwd) Then
                        'password is correct
                        Return processSuccess(context, id, True, forceUpdate(context))
                    Else
                        'password is wrong
                        Return processPasswordError(context, id)
                    End If
                Else
                    'no password read, so the user is not existing
                    Return processRegister(context, id)
                End If
            ElseIf forceUpdate(context) Then
                'if there is a forceUpdate, ignore randomkey from cookie
                Return processLogin(context, id)
            Else
                'no password input
                Dim randomkey As String = Nothing
                If context.userInput(query.userRandomKey, cookie.userRandomKey, randomkey) Then
                    Dim realrndkey As String = Nothing
                    If userRandomKey(id, realrndkey) Then
                        If strsame(randomkey, realrndkey) Then
                            'randomkey is correct
                            Return processSuccess(context, id, False, False)
                        Else
                            'the randomkey is wrong
                            Return processLogin(context, id)
                        End If
                    Else
                        'no randomkey read, maybe the user is not existing, or not logged in before, or internal error
                        If userPassword(id, Nothing) Then
                            'has password, login
                            Return processLogin(context, id)
                        Else
                            Return processRegister(context, id)
                        End If
                    End If
                Else
                    'no random key also found in cookie, should login
                    Return processLogin(context, id)
                End If
            End If
        Else
            'no id input
            Return processLogin(context)
        End If
    End Function
End Class
